package com.sh.data.engine.domain.authority.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sh.data.engine.common.constants.Constants;
import com.sh.data.engine.common.exception.BusinessException;
import com.sh.data.engine.domain.authority.model.domain.*;
import com.sh.data.engine.domain.authority.service.DataAuthService;
import com.sh.data.engine.domain.authority.service.ProjectAuthService;
import com.sh.data.engine.domain.authority.service.ProjectTblService;
import com.sh.data.engine.domain.authority.service.UserProjectService;
import com.sh.data.engine.domain.base.model.enums.RightEnum;
import com.sh.data.engine.domain.dataasset.model.domain.TableInfoBizDomain;
import com.sh.data.engine.domain.dataasset.model.param.QueryTableParam;
import com.sh.data.engine.domain.dataasset.service.TableService;
import com.sh.data.engine.domain.dataasset.service.TblPropService;
import com.sh.data.engine.domain.normalization.research.themedesign.model.domain.ThemeDomain;
import com.sh.data.engine.domain.normalization.research.themedesign.service.ThemeService;
import com.sh.data.engine.domain.util.ConvertUtil;
import com.sh.data.engine.domain.workspace.index.model.domain.ProjectDomain;
import com.sh.data.engine.domain.workspace.index.service.ProjectService;
import com.sh.data.engine.domain.workspace.manager.model.domain.UserDomain;
import com.sh.data.engine.domain.workspace.manager.service.UserService;
import com.sh.data.engine.repository.dao.authority.entity.ProjectTblEntity;
import com.sh.data.engine.repository.dao.authority.entity.UserProjectEntity;
import com.sh.data.engine.repository.dao.dataasset.entity.TblPropEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author tinglan.ys
 * @description:
 * @date 2022/8/11 下午5:48
 */
@Service
@Slf4j
public class DataAuthServiceImpl implements DataAuthService {

    @Autowired
    private UserService userService;

    @Autowired
    private UserProjectService userProjectService;

    @Autowired
    private TblPropService tblPropService;

    @Autowired
    private ProjectAuthService projectAuthService;

    @Autowired
    private TableService tableService;

    @Autowired
    private ThemeService themeService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private ProjectTblService projectTblService;

    //该id在不同的环境不一样
    @Value("${super.admin.id}")
    private String SUPER_ADMIN;

    @Override
    public IPage<DataAuthDomain> getDataAuth(String userName, Integer pageNum, Integer pageSize) {
//        // 1.分页查询用户列表
//        IPage<UserDomain> userList = userService.getUserListWithoutAdmin(userName, pageNum, pageSize);
//
//        IPage<DataAuthDomain> dataAuthDomainPageResult =
//            userList.convert(e -> Convert.convert(DataAuthDomain.class, e));
//
//        for (DataAuthDomain dataAuthDomain : dataAuthDomainPageResult.getRecords()) {
//            // 2.查询每个用户拥有的工作空间
//            List<Long> projectIds =
//                userProjectService
//                    .list(
//                        new LambdaQueryWrapper<UserProjectEntity>()
//                            .eq(UserProjectEntity::getUserId, dataAuthDomain.getId()))
//                    .stream()
//                    .map(UserProjectEntity::getProjectId)
//                    .collect(Collectors.toList());
//
//            // 3.拼装所有空间的表个数
//            int tblNumTotal = 0;
//            for (Long projectId : projectIds) {
//                List<TblPropEntity> tblPropByProjectId = tblPropService.getTblPropByProjectId(projectId);
//                if (CollectionUtils.isNotEmpty(tblPropByProjectId)) {
//                    tblNumTotal = tblNumTotal + tblPropByProjectId.size();
//                }
//            }
//            dataAuthDomain.setTblNumTotal(tblNumTotal);
//        }
//        return dataAuthDomainPageResult;
        return null;
    }

    @Override
    public List<DataAuthDetailDomain> getDataAuthSec(String userId) {

        List<ProjectDomain> projectAuthByUserId = projectAuthService.getProjectAuthByUserId(userId);
        List<DataAuthDetailDomain> dataAuthDetailDomainList =
            ConvertUtil.copyProperties(projectAuthByUserId, DataAuthDetailDomain.class);
        for (DataAuthDetailDomain dataAuthDetailDomain : dataAuthDetailDomainList) {
            // 拼接表数量
            List<TblPropEntity> tblPropByProjectId =
                tblPropService.getTblPropByProjectId(dataAuthDetailDomain.getId());
            if (CollectionUtils.isNotEmpty(tblPropByProjectId)) {
                dataAuthDetailDomain.setTblNum(tblPropByProjectId.size());
            } else {
                dataAuthDetailDomain.setTblNum(0);
            }
        }
        return dataAuthDetailDomainList;
    }

    private List<UserAuthTblDomain> getTblList(Long projectId) {

        QueryTableParam queryTableParam = new QueryTableParam();
        List<TableInfoBizDomain> tableList = tableService.getTableList(projectId, queryTableParam);

        List<UserAuthTblDomain> userAuthTblDomains =
            ConvertUtil.copyProperties(tableList, UserAuthTblDomain.class);

        // 拼装themeName
        for (UserAuthTblDomain userAuthTblDomain : userAuthTblDomains) {
            if (userAuthTblDomain.getThemeId() != null) {
                ThemeDomain themeDomain = themeService.getThemeById(userAuthTblDomain.getThemeId());
                if (themeDomain != null) {
                    userAuthTblDomain.setThemeName(themeDomain.getThemeName());
                }
            }
        }
        return userAuthTblDomains;
    }

    @Override
    public List<UserAuthTblThemeDomain> getDataAuthTblList(Long projectId, String userId) {
        // 首先获取该空间下拥有的表信息
        List<UserAuthTblDomain> tblList;
        try {
            tblList = getTblList(projectId);
            // fix bug 当long类型的tblId大于16位 例如 1517437887025577984 页面上返回的json显示 1517437887025578000 精度会出现截断
            // 只能都变成String类型传给前端
            for (UserAuthTblDomain userAuthTblDomain : tblList) {
                userAuthTblDomain.setTblIdStr(userAuthTblDomain.getTblId().toString());
            }
        } catch (Exception e) {
            log.error(e.toString());
            throw new BusinessException(
                "查询 " + projectService.getProjectById(projectId).getName() + " 空间下属表出错，请检查该空间下的数据源");
        }
        // 查询所有主题
        List<ThemeDomain> themeDomainList = themeService.getThemesByProjectId(projectId);

        // 把主题信息封装到返回类中 然后通过遍历，把对应的表信息塞到这个返回类中
        List<UserAuthTblThemeDomain> userAuthTblDomainList =
            ConvertUtil.copyProperties(themeDomainList, UserAuthTblThemeDomain.class);

        for (UserAuthTblThemeDomain userAuthTblThemeDomain : userAuthTblDomainList) {
            // 遍历每一个主题
            List<UserAuthTblDomain> userAuthTblDomainList1 = new ArrayList<>();
            for (UserAuthTblDomain userAuthTblDomain : tblList) {
                // 根据主题Id去匹配，根据tblList里面的themeId去匹配，塞入信息
                if (userAuthTblThemeDomain.getId().equals(userAuthTblDomain.getThemeId())) {
                    userAuthTblDomainList1.add(userAuthTblDomain);
                }
            }
            userAuthTblThemeDomain.setUserAuthTblDomains(userAuthTblDomainList1);
        }

        // 以上获取了所有主题，以及各个主题下的表
        // 以下需要查询ProjectTblEntity，把各个表的权限信息再写到返回类中

        List<ProjectTblEntity> projectTblEntities =
            projectTblService.list(
                new LambdaQueryWrapper<ProjectTblEntity>()
                    .eq(ProjectTblEntity::getUserId, userId)
                    .eq(ProjectTblEntity::getProjectId, projectId));

        if (CollectionUtils.isEmpty(projectTblEntities)) {
            // 没有权限信息 返回整个list
            return userAuthTblDomainList;
        } else {
            // 有权限信息，将权限信息写进UserAuthTblDomain
            for (ProjectTblEntity projectTblEntity : projectTblEntities) {
                for (UserAuthTblDomain userAuthTblDomain : tblList) {
                    if (projectTblEntity.getTblId() != null) {
                        // 根据tblId匹配 写入权限信息
                        if (projectTblEntity.getTblId().equals(userAuthTblDomain.getTblId())) {
                            userAuthTblDomain.setAuth(projectTblEntity.getAuth());
                        }
                    }
                }
            }
        }
        return userAuthTblDomainList;
    }

    @Override
    public Boolean saveDataAuth(ProjectTblDomain projectTblDomain) {

        String userId = projectTblDomain.getUserId();
        Long projectId = projectTblDomain.getProjectId();

        // 先删除原来的
        projectTblService.remove(
            new LambdaQueryWrapper<ProjectTblEntity>()
                .eq(ProjectTblEntity::getUserId, userId)
                .eq(ProjectTblEntity::getProjectId, projectId));

        // 再保存
        List<ProjectTblEntity> projectTblEntities = new ArrayList<>();
        for (TblAuthDomain tblAuthDomain : projectTblDomain.getTblAuthDomainList()) {
            ProjectTblEntity projectTblEntity = new ProjectTblEntity();
            projectTblEntity.setUserId(userId);
            projectTblEntity.setProjectId(projectId);
            projectTblEntity.setTblId(tblAuthDomain.getTblId());
            projectTblEntity.setAuth(tblAuthDomain.getAuth());
            projectTblEntities.add(projectTblEntity);
        }
        projectTblService.saveBatch(projectTblEntities);

        return true;
    }

    @Override
    public String getTblAuth(Long projectId, String userId, Long tblId) {
        if (userId == null || userId.equals(SUPER_ADMIN)) {
            // 管理员用户拥有所有表的权限
            return RightEnum.RW.getCode();
        }

        List<ProjectDomain> projectAuthByUserId = projectAuthService.getProjectAuthByUserId(userId);
        if (CollectionUtils.isEmpty(projectAuthByUserId)) {
            // 该用户没有下没有空间，所以没有任何表的权限
            return RightEnum.NONE.getCode();
        }

        ProjectTblEntity projectTblEntity =
            projectTblService.getOne(
                new LambdaQueryWrapper<ProjectTblEntity>()
                    .eq(ProjectTblEntity::getUserId, userId)
                    .eq(ProjectTblEntity::getProjectId, projectId)
                    .eq(ProjectTblEntity::getTblId, tblId));
        if (projectTblEntity == null) {
            return RightEnum.RW.getCode();
        } else {
            return projectTblEntity.getAuth();
        }
    }

    @Override
    public Map<Long, String> getTblAuthMap(Long projectId, String userId, List<Long> tblId) {
        if (CollectionUtils.isEmpty(tblId)) {
            return Maps.newHashMap();
        }
        Map<Long, String> res = Maps.newHashMap();
        if (userId.equals(SUPER_ADMIN)) {
            // 管理员用户拥有所有表的权限
            tblId.forEach(
                e -> {
                    res.put(e, RightEnum.RW.getCode());
                });
            return res;
        }

        List<ProjectDomain> projectAuthByUserId = projectAuthService.getProjectAuthByUserId(userId);
        if (CollectionUtils.isEmpty(projectAuthByUserId)) {
            // 该用户没有下没有空间，所以没有任何表的权限
            tblId.forEach(
                e -> {
                    res.put(e, RightEnum.NONE.getCode());
                });
            return res;
        }

        List<ProjectTblEntity> projectTblEntities =
            projectTblService.list(
                new LambdaQueryWrapper<ProjectTblEntity>()
                    .eq(ProjectTblEntity::getUserId, userId)
                    .eq(ProjectTblEntity::getProjectId, projectId)
                    .in(ProjectTblEntity::getTblId, tblId));
        if (projectTblEntities == null) {
            tblId.forEach(
                e -> {
                    res.put(e, RightEnum.RW.getCode());
                });
            return res;
        }

        projectTblEntities.forEach(e -> {
            res.put(e.getTblId(), e.getAuth());
        });


        return res;

    }

    @Override
    public List<ProjectTblEntity> getSomeTblAuth(Long projectId, String userId, List<Long> tblIds) {
        if (CollectionUtils.isEmpty(tblIds)) {
            return Lists.newArrayList();
        }
        LambdaQueryWrapper<ProjectTblEntity> eq =
            new LambdaQueryWrapper<ProjectTblEntity>()
                .eq(ProjectTblEntity::getProjectId, projectId)
                .eq(ProjectTblEntity::getUserId, userId)
                .in(ProjectTblEntity::getTblId, tblIds);

        List<ProjectTblEntity> projectTblEntities = projectTblService.list(eq);

        return projectTblEntities;
    }
}
